/*
===========================================================================
Copyright (C) 2013-2014 Avotu Briezhaudzetava

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.

===========================================================================
*/

//
// includes
//
#include "gui_precursors.h"
#include "ui_gui_precursors.h"
#include <QSqlQuery>
#include "gui_main.h"
#include <QMessageBox>

/*
================
construct
================
*/
Gui_Precursors::Gui_Precursors( QWidget *parent ) : QDialog( parent ), ui( new Ui::Gui_Precursors ) {
    ui->setupUi( this );

    this->toggleWidgetVisibility( false );
    this->connect( this->ui->widgetAddEdit, SIGNAL( visibilityChanged( bool )), this, SLOT( toggleWidgetVisibility( bool )));

    // set up view
    this->listModel = new PrecursorModel( this );
    this->ui->listPrecursors->setModel( this->listModel );

    //this->fillUnits();
    this->on_checkboxSolvent_stateChanged( this->ui->checkboxSolvent->checkState());
}

/*
================
destruct
================
*/
Gui_Precursors::~Gui_Precursors() {
    delete ui;
    delete this->listModel;
}

/*
================
checkboxSolvent->stateChanged
================
*/
void Gui_Precursors::on_checkboxSolvent_stateChanged( int state ) {    
    if ( state == Qt::Checked ) {
        this->ui->spinboxDensity->setEnabled( true );
        m.fillUnits( this->ui->comboUnits, true );
    } else {
        this->ui->spinboxDensity->setDisabled( true );
        m.fillUnits( this->ui->comboUnits, false );
    }
}

/*
================
toggleWidgetVisibility
================
*/
void Gui_Precursors::toggleWidgetVisibility( bool visible ) {
    if ( visible ) {
        this->ui->widgetAddEdit->setEnabled( true );
        this->ui->widgetAddEdit->show();
        this->ui->buttonAdd->setDisabled( true );
        this->ui->buttonEdit->setDisabled( true );
        this->ui->buttonRemove->setDisabled( true );
        this->ui->listPrecursors->setDisabled( true );
        this->clearItemState();
    } else {
        this->ui->widgetAddEdit->setDisabled( true );
        this->ui->widgetAddEdit->hide();
        this->ui->buttonAdd->setEnabled( true );
        this->ui->buttonEdit->setEnabled( true );
        this->ui->buttonRemove->setEnabled( true );
        this->ui->listPrecursors->setEnabled( true );
    }
}

/*
================
readItemState
================
*/
void Gui_Precursors::readItemState() {
    PrecursorEntry *pPtr;

    if ( this->currentState() != Edit )
        return;

    pPtr = m.precursorForId( this->ui->listPrecursors->model()->data( this->ui->listPrecursors->currentIndex(), Qt::UserRole ).toInt());
    if ( pPtr == NULL )
        return;

    // full units
    m.fillUnits( this->ui->comboUnits, pPtr->isSolvent());

    // set values
    this->ui->textTitle->setText( pPtr->title());
    this->ui->textLot->setText( pPtr->lot());
    this->ui->comboUnits->setCurrentIndex( Main::unitsToIndex( this->ui->comboUnits, pPtr->units()));
    if ( pPtr->isSolvent())
        this->ui->checkboxSolvent->setChecked( true );
    else
        this->ui->checkboxSolvent->setChecked( false );
    this->ui->spinboxDensity->setValue( pPtr->density());
    this->ui->spinboxBase->setValue( pPtr->baseAmount());
}

/*
================
clearItemState
================
*/
void Gui_Precursors::clearItemState() {
    this->ui->textTitle->clear();
    this->ui->textLot->clear();
    this->ui->checkboxSolvent->setChecked( false );
    this->ui->spinboxDensity->setValue( 1.0f );
    this->ui->spinboxBase->setValue( 0.0f );
}

/*
================
saveItemState
================
*/
void Gui_Precursors::saveItemState() {
    this->listModel->beginReset();

    if ( this->currentState() == Add ) {
        m.addPrecursor(
                    this->ui->textTitle->text(),
                    this->ui->textLot->text(),
                    this->ui->spinboxBase->value(),
                    static_cast<Common::Units>( m.indexToUnits( this->ui->comboUnits )),
                    this->ui->checkboxSolvent->isChecked(),
                    this->ui->spinboxDensity->value());
    } else if ( this->currentState() == Edit ) {
        PrecursorEntry *pPtr;

        pPtr = m.precursorForId( this->ui->listPrecursors->model()->data( this->ui->listPrecursors->currentIndex(), Qt::UserRole ).toInt());
        if ( pPtr == NULL )
            return;

        pPtr->setTitle( this->ui->textTitle->text());
        pPtr->setLot( this->ui->textLot->text());
        pPtr->setUnits( static_cast<Common::Units>( m.indexToUnits( this->ui->comboUnits )));
        if ( this->ui->checkboxSolvent->isChecked())
            pPtr->setSolvent();
        else
            pPtr->setSolvent( false );
        pPtr->setDensity( this->ui->spinboxDensity->value());
        pPtr->setBaseAmount( this->ui->spinboxBase->value());
    }

    this->listModel->endReset();
}

/*
================
toggleWidgetState
================
*/
void Gui_Precursors::toggleWidgetState( State state ) {
    this->m_state = state;

    switch ( state ) {
    case Add:
        this->toggleWidgetVisibility();
        m.fillUnits( this->ui->comboUnits, false );
        this->ui->buttonAccept->setFocus();
        break;

    case Edit:
        this->toggleWidgetVisibility();
        this->readItemState();
        this->ui->buttonAccept->setFocus();
        break;

    case NoState:
    default:
        this->toggleWidgetVisibility( false );
        this->ui->buttonClose->setFocus();
        break;
    }
}

/*
================
buttonAdd->clicked
================
*/
void Gui_Precursors::on_buttonAdd_clicked() {
    this->toggleWidgetState( Add );
}

/*
================
buttonEdit->clicked
================
*/
void Gui_Precursors::on_buttonEdit_clicked() {
    this->toggleWidgetState( Edit );
}

/*
================
buttonRemove->clicked
================
*/
void Gui_Precursors::on_buttonRemove_clicked() {
    QSqlQuery query;
    PrecursorEntry *pPtr;

    pPtr = m.precursorForId( this->ui->listPrecursors->model()->data( this->ui->listPrecursors->currentIndex(), Qt::UserRole ).toInt());
    if ( pPtr == NULL )
        return;

    // begin reset
    this->listModel->beginReset();

    // remove from internal list
    m.precursorList.removeOne( pPtr );

    // remove from database
    query.exec( QString( "delete from precursors where id=%1" ).arg( pPtr->id()));

    // end reset
    this->listModel->endReset();

    // emit signal to main activity
    Gui_Main *guiPtr = qobject_cast<Gui_Main *>( this->parent());
    emit guiPtr->precursorListChanged();
}

/*
================
buttonAccept->clicked
================
*/
void Gui_Precursors::on_buttonAccept_clicked() {
    if ( this->currentState() == NoState )
        return;

    // failsafe - name
    if ( this->ui->textTitle->text().isEmpty()) {
        QMessageBox::warning( this, this->tr( "Precursor management" ),
                                    this->tr( "Please specify precursor title" ), QMessageBox::Ok );
        return;
    }

    // failsafe - LOT/Batch
    if ( this->ui->textLot->text().isEmpty()) {
        QMessageBox::warning( this, this->tr( "Precursor management" ),
                                    this->tr( "Please specify LOT/Batch" ), QMessageBox::Ok );
        return;
    }

    // failsafe - solvent density
    if ( this->ui->checkboxSolvent->isChecked() && this->ui->spinboxDensity->value() == 0.0f ) {
        QMessageBox::warning( this, this->tr( "Precursor management" ),
                                    this->tr( "Please input solvent density" ), QMessageBox::Ok );
        return;
    }

    // all ok - proceed!
    this->saveItemState();
    this->toggleWidgetState();

    // emit signal to main activity
    Gui_Main *guiPtr = qobject_cast<Gui_Main *>( this->parent());
    emit guiPtr->precursorListChanged();
}

/*
================
comboUnits->currentIndexChanged
================
*/
void Gui_Precursors::on_comboUnits_currentIndexChanged( int index ) {
    PrecursorEntry *pPtr;
    Common::Units units = static_cast<Common::Units>( index );

    switch ( units ) {
    // converting g/mL to kg/L
    case Common::Kilograms:
    case Common::Litres:
        this->ui->spinboxBase->setDecimals( 4 );

        // scale down
        if ( this->lastUnits() == Common::Millilitres || this->lastUnits() == Common::Grams )
            this->ui->spinboxBase->setValue( this->ui->spinboxBase->value() / 1000.0f );
        break;

    default:
        // converting kg/L to g/mL
    case Common::Millilitres:
    case Common::Grams:
        // scale up
        if ( this->lastUnits() == Common::Kilograms || this->lastUnits() == Common::Litres )
            this->ui->spinboxBase->setValue( this->ui->spinboxBase->value() * 1000.0f );

        this->ui->spinboxBase->setDecimals( 1 );
        break;
    }

    // special hack for solvents (converter)
    pPtr = m.precursorForId( this->ui->listPrecursors->model()->data( this->ui->listPrecursors->currentIndex(), Qt::UserRole ).toInt());
    if ( pPtr != NULL ) {
        // conversion valid only for solvents
        if ( pPtr->isSolvent()) {
            switch ( units ) {
            // converting g/kg to mL/L
            case Common::Litres:
            case Common::Millilitres:
                if ( this->lastUnits() == Common::Grams || this->lastUnits() == Common::Kilograms )
                    this->ui->spinboxBase->setValue( this->ui->spinboxBase->value() / this->ui->spinboxDensity->value());
                break;

            default:
            // converting mL/L to g/kg
            case Common::Kilograms:
            case Common::Grams:
                if ( this->lastUnits() == Common::Millilitres || this->lastUnits() == Common::Litres )
                    this->ui->spinboxBase->setValue( this->ui->spinboxBase->value() * this->ui->spinboxDensity->value());
                break;
            }
        }
    }
    this->m_lastUnits = units;
}

/*
================
buttonClose->clicked
================
*/
void Gui_Precursors::on_buttonClose_clicked() {
    this->close();
}
